#include "rc522.h"

//#define uint8_t unsigned char
//#define u32 unsigned int
	
//79E22465
//438FC79A
// M1卡分为16个扇区，每个扇区由四个块（块0、块1、块2、块3）组成
// 将16个扇区的64个块按绝对地址编号为：0~63
// 第0个扇区的块0（即绝对地址0块），用于存放厂商代码，已经固化不可更改 
// 每个扇区的块0、块1、块2为数据块，可用于存放数据
// 每个扇区的块3为控制块（绝对地址为:块3、块7、块11.....）包括密码A，存取控制、密码B等

/*******************************
*连线说明：
*1--SDA  <----->PA4
*2--SCK  <----->PA5
*3--MOSI <----->PA7
*4--MISO <----->PA6
*5--悬空
*6--GND <----->GND
*7--RST <----->PB0
*8--VCC <----->VCC
************************************/
/*全局变量*/
uint8_t KEY_A[6]= {0xff,0xff,0xff,0xff,0xff,0xff};
int flag;
//uint8_t KEY_A[6]= {0x01, 0x01, 0x01, 0x01, 0x01, 0x01};

uint8_t KEY_B[6]= {0xff,0xff,0xff,0xff,0xff,0xff};

//uint8_t KEY_B[6]={0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
unsigned char RFID2[16]= {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x80,0x29,0xff,0xff,0xff,0xff,0xff,0xff};
unsigned char DATA[16];			//存放数据
unsigned char DATA0[16]= {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
unsigned char DATA1[16]= {0x12,0x34,0x56,0x78,0x9A,0x00,0xff,0x07,0x80,0x29,0xff,0xff,0xff,0xff,0xff,0xff};

unsigned char CT[2];//卡类型   
unsigned char SN[4]; //卡号 

char SN_str[8];//卡号字符串    
unsigned char RFID[16];			//存放RFID 

unsigned char lxl_bit=0;
unsigned char card1_bit=0;
unsigned char card2_bit=0;
unsigned char card3_bit=0;
unsigned char card4_bit=0;
unsigned char total=0;
unsigned char lxl[4]={196,58,104,217};
unsigned char card_1[4]={83,106,11,1};
unsigned char card_2[4]={208,121,31,57};
unsigned char card_3[4]={176,177,143,165};
unsigned char card_4[4]={5,158,10,136};

uint8_t KEY[6]={0xff,0xff,0xff,0xff,0xff,0xff};
uint8_t AUDIO_OPEN[6] = {0xAA, 0x07, 0x02, 0x00, 0x09, 0xBC};
unsigned char RFID1[16]={0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x80,0x29,0xff,0xff,0xff,0xff,0xff,0xff};
/*函数声明*/
unsigned char status;
unsigned char s=0x08;
#define          BEEP_0()            GPIO_ResetBits( GPIOB, GPIO_Pin_9 )
#define          BEEP_1()            GPIO_SetBits ( GPIOB, GPIO_Pin_9 )
#define   RC522_DELAY()  delay_us( 20 )

unsigned char Flag_find_card = 0;

void bytesToHexstring(unsigned char *bytes, int bytelength, char *hexstring, int hexstrlength);



void RC522_Write(uint8_t addr,uint8_t DATA[16])       ///写
{
		//uint8_t i = 0;
	
    status = PcdRequest(PICC_REQALL,CT);//寻卡//扫描
	
    if(status==MI_OK)// 寻卡成功 扫描到了
    {
        status=MI_ERR;
        status = PcdAnticoll(SN);// 防冲撞 获得UID 存入SN   //获取卡号
     }
     if (status==MI_OK)// 防冲撞成功   //再次获得卡号，
     {
        status = MI_ERR;
        //printf("card ID:%d",SN);
//		  	USART2TxData_hex(SN,4);        //通过串口发送卡号
        status = PcdSelect(SN);
     }
    if(status == MI_OK)    //选卡成功      
    {
        status = MI_ERR;
				status = PcdAuthState(0x60, addr, KEY_A, SN);
        if(status == MI_OK)//验证成功
        {
//            USART2TxStr("PcdAuthState(A) success\r\n");
        }
        else
        {
//            USART2TxStr("PcdAuthState(A) failed\r\n");
			status = MI_OK;
        }
		
    }
	if(status == MI_OK)//写卡成功
    {
        status = MI_ERR;
				status =PcdAuthState(0x60,addr,KEY_A,SN);
    }
	if(status == MI_OK)//读卡成功
  {
        status = MI_ERR;
		   flag=1;
        // 写数据到M1卡一块
        status = PcdWrite(addr, DATA);
        if(status == MI_OK)//写卡成功
        {
//            USART2TxStr("PcdWrite(DATA) success\r\n");
					flag=1;
        }
        else
        {
//            USART2TxStr("PcdWrite(DATA) failed\r\n");
						delay_ms(3000);
        }
   }
 }
 
void RC522_Read(uint8_t addr)       //转给一个0X01
{
		uint8_t i = 0;
    status = PcdRequest(PICC_REQALL,CT);//寻卡
	  //USART2TxStr("find car  "); 
    if(status==MI_OK)
    {
        status=MI_ERR;
        status = PcdAnticoll(SN);
    }
    if (status==MI_OK)
    {
        status = MI_ERR;
        //printf("card ID:%d",SN);
			
			//  USART2TxStr("Card ID =");      //卡的ID是什么？
			
				bytesToHexstring(SN,4,SN_str,8);
			
//				USART2TxStr(SN_str);
//				LCD_ShowString(16*8,16*5,SN_str);   //显示
//				LCD.ShowString(16*8,16*5,SN_str);
//				BEEP_0();     
//				delay_ms(20);      //蜂鸣器响
//			  BEEP_1();
			
			  Flag_find_card = 1;
        status = PcdSelect(SN);
    }
    if(status == MI_OK)
    {
        status = MI_ERR;
				status = PcdAuthState(0x60, addr, KEY_A, SN);
        if(status == MI_OK)//验证成功
        {
            //printf("PcdAuthState(A) success\r\n");
//					USART2TxStr("PcdAuthState(A) success\r\n"); 
        }
        else
        {
            //printf("PcdAuthState(A) failed\r\n");
//					USART2TxStr("PcdAuthState(A) failed\r\n"); 
						status = MI_OK;
        }
				status = PcdAuthState(0x61,addr, KEY_B, SN);
        if(status == MI_OK)//验证成功
        {
					flag=1;
//            USART2TxStr("PcdAuthState(B) success\r\n");
        }
        else
        {
//            USART2TxStr("PcdAuthState(B) failed\r\n");
        }
    }
    if(status == MI_OK)//验证成功
    {
        status = MI_ERR;
        status = PcdRead(addr, DATA);
        if(status == MI_OK)//读卡成功
        {
//           USART2TxStr("DATA:");
//						Uart2.SendString("DATA:");
            for(i = 0; i < 16; i++)
            {
                //printf("%02x", DATA[i]);
//							  USART2TxChar(DATA[i]);
            }
//           USART2TxStr("\r\n");
        }
        else
        {
//            USART2TxStr("PcdRead() failed\r\n");
        }
    }
}


void RC522_wr(void)
{
    uint8_t i = 0;
		unsigned char test_addr=0x09;
    status = PcdRequest(PICC_REQALL,CT);//寻卡
    if(status==MI_OK)// 寻卡成功
    {
        status=MI_ERR;
        status = PcdAnticoll(SN);// 防冲撞 获得UID 存入SN
    }
    if (status==MI_OK)// 防冲撞成功
    {
        status = MI_ERR;
        //printf("card ID:%d",SN);
//			USART2TxData_hex(SN,4);
        status = PcdSelect(SN);
    }
    if(status == MI_OK)//选卡成功
    {
        status = MI_ERR;
				status = PcdAuthState(0x60, 0x09, KEY_A, SN);
        if(status == MI_OK)//验证成功
        {
//            USART2TxStr("PcdAuthState(A) success\r\n");
        }
        else
        {
//           USART2TxStr("PcdAuthState(A) failed\r\n");
						status = MI_OK;
						goto P1;
        }
				status = PcdAuthState(0x61, test_addr, KEY_B, SN);
        if(status == MI_OK)//验证成功
        {
//            USART2TxStr("PcdAuthState(B) success\r\n");
        }
        else
        {
//            USART2TxStr("PcdAuthState(B) failed\r\n");
        }
    }

    if(status == MI_OK)//验证成功
    {
//				USART2TxStr("\r\nverification successful\r\n");
        status = MI_ERR;
        // 读取M1卡一块数据 块地址 读取的数据 注意：因为上面验证的扇区是3扇区，所以只能对2扇区的数据进行读写，即0x0C-0x0F这个范围，超出范围读取失败。
        status = PcdRead(test_addr, DATA);
        if(status == MI_OK)//读卡成功
        {
            // printf("RFID:%s\r\n", RFID);
//           USART2TxStr("DATA:");
            for(i = 0; i < 16; i++)
            {
                //printf("%02x", DATA[i]);
//							USART2TxChar(DATA[i]);
            }
//           USART2TxStr("\r\n");
        }
        else
        {
//            USART2TxStr("PcdRead() failed\r\n");
        }
    }

    if(status == MI_OK)//读卡成功
    {
        status = MI_ERR;
        // 写数据到M1卡一块
        status = PcdWrite(test_addr, RFID1);
        if(status == MI_OK)//写卡成功
        {
//           USART2TxStr("PcdWrite(RFID1) success\r\n");
        }
        else
        {
//            USART2TxStr("PcdWrite(RFID1) failed\r\n");
			delay_ms(3000);
        }
    }

P1:	
	if(status == MI_OK)//写卡成功
    {
        status = MI_ERR;
				status =PcdAuthState(0x60,0x09,KEY,SN);
    }
	
	if(status == MI_OK)//验证成功
    {
        status = MI_ERR;
        // 读取M1卡一块数据 块地址 读取的数据 注意：因为上面验证的扇区是3扇区，所以只能对2扇区的数据进行读写，即0x0C-0x0F这个范围，超出范围读取失败。
        status = PcdRead(test_addr, DATA);
        if(status == MI_OK)//读卡成功
        {
            // printf("RFID:%s\r\n", RFID);
//            USART2TxStr("DATA:");
            for(i = 0; i < 16; i++)
            {
                //printf("%02x", DATA[i]);
//							USART2TxChar(DATA[i]);
            }
//            USART2TxStr("\r\n");
        }
        else
        {
//            USART2TxStr("PcdRead() failed\r\n");
        }
    }
	
	if(status == MI_OK)//读卡成功
    {
        status = MI_ERR;
        // 写数据到M1卡一块
        status = PcdWrite(test_addr, RFID2);
        if(status == MI_OK)//写卡成功
        {
//             USART2TxStr("PcdWrite(RFID2) success\r\n");
        }
        else
        {
//             USART2TxStr("PcdWrite(RFID2) failed\r\n");
						delay_ms(3000);
        }
    }

    if(status == MI_OK)//写卡成功
    {
        status = MI_ERR;
        // 读取M1卡一块数据 块地址 读取的数据
        status = PcdRead(test_addr, DATA);
        if(status == MI_OK)//读卡成功
        {
            // printf("DATA:%s\r\n", DATA);
//            USART2TxStr("DATA:");
            for(i = 0; i < 16; i++)
            {
                //printf("%02x", DATA[i]);
//							USART2TxChar(DATA[i]);
            }
//             USART2TxStr("\r\n");
        }
        else
        {
//             USART2TxStr("PcdRead() failed\r\n");
        }
    }

    if(status == MI_OK)//读卡成功
    {
        status = MI_ERR;
//		USART2TxStr("RC522_Handle1() run finished after 1 second!\r\n");
        delay_ms(1000);
    }
}



void RC522_Handel(void)
{
    status = PcdRequest(PICC_REQALL,CT);//寻卡
    //printf("\r\nstatus>>>>>>%d\r\n", status);
    if(status==MI_OK)//寻卡成功
    {
         status=MI_ERR;
         status = PcdAnticoll(SN);//防冲撞	       
    }
    if (status==MI_OK)//防衝撞成功
    {
        status=MI_ERR;		
        //printf("CARD ID:%d",SN);
//			USART2TxData_hex(SN,4);
			
        if((SN[0]==lxl[0])
	        &&(SN[1]==lxl[1])
	        &&(SN[2]==lxl[2])
	        &&(SN[3]==lxl[3]))
        {
            lxl_bit=1;
//           USART2TxStr("\r\nThe User is:card_0\r\n");
        }
        if((SN[0]==card_1[0])
	        &&(SN[1]==card_1[1])
	        &&(SN[2]==card_1[2])
	        &&(SN[3]==card_1[3]))
        {
            card1_bit=1;
//           USART2TxStr("\r\nThe User is:card_1\r\n");
            
        }
        if((SN[0]==card_2[0])
	        &&(SN[1]==card_2[1])
	        &&(SN[2]==card_2[2])
	        &&(SN[3]==card_2[3]))
        {
            card2_bit=1;
//           USART2TxStr("\r\nThe User is:card_2\r\n");
        }
        
        if((SN[0]==card_3[0])
	        &&(SN[1]==card_3[1])
	        &&(SN[2]==card_3[2])
	        &&(SN[3]==card_3[3]))
        {
            card3_bit=1;
//           USART2TxStr("\r\nThe User is:card_3\r\n");
        }
        if((SN[0]==card_4[0])
	        &&(SN[1]==card_4[1])
	        &&(SN[2]==card_4[2])
	        &&(SN[3]==card_4[3]))
        {
            card4_bit=1;
//            USART2TxStr("\r\nThe User is:card_4\r\n");
        }
        //total=card1_bit+card2_bit+card3_bit+card4_bit+lxl_bit;
        status =PcdSelect(SN);
    }
    else
    {
       // TODO 
    }
		if(status==MI_OK)//选卡成功
		{
//				USART2TxStr("\r\nselect card successful\r\n");
				status=MI_ERR;
				status =PcdAuthState(0x60,0x09,KEY,SN);
		}
    if(status==MI_OK)//验证成功
    {
//				USART2TxStr("\r\nverification successful\r\n");
        status=MI_ERR;
        status=PcdRead(s,RFID);
    }
    if(status==MI_OK)//读卡成功
    {
//				USART2TxStr("\r\nread card successful\r\n");
        status=MI_ERR;
        delay_ms(100);
    }	
}

void RC522_Init ( void )
{
	SPI1_Init();									//软件spi初始化
	RC522_Reset_Disable();
	RC522_CS_Disable();
  PcdReset ();
	M500PcdConfigISOType ( 'A' );//设置工作方式
}


/****************************
SPI部分
*****************************/


void SPI1_Init(void)	
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);


    // RST
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);

			// CS
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);					 //根据设定参数初始化PA15

    // SCK
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    // MISO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 		 //输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    // MOSI
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;	 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}


/**************************************
 * 函数名：SPI_RC522_SendByte
 * 描述  ：向RC522发送1 Byte 数据
 * 输入  ：byte，要发送的数据
 * 返回  : RC522返回的数据
 * 调用  ：内部调用
 **************************************/
void SPI_RC522_SendByte ( uint8_t byte )
{
	uint8_t counter;
	
	for(counter = 0; counter < 8; counter++)
	{     
		if ( byte & 0x80 )
			RC522_MOSI_1 ();
		else 
			RC522_MOSI_0 ();

		RC522_DELAY();
		RC522_SCK_0 ();
		
		RC522_DELAY();
		RC522_SCK_1();
		
		RC522_DELAY();
		byte <<= 1; 
	} 
}

/*
 * 函数名：SPI_RC522_ReadByte
 * 描述  ：从RC522发送1 Byte 数据
 * 输入  ：无
 * 返回  : RC522返回的数据
 * 调用  ：内部调用
 */
uint8_t SPI_RC522_ReadByte ( void )
{
	uint8_t counter;
	uint8_t SPI_Data;
	for(counter=0;counter<8;counter++)
	{
		SPI_Data <<= 1;
		RC522_SCK_0 ();
		
		RC522_DELAY();
		if ( RC522_MISO_GET() == 1)
			SPI_Data |= 0x01;
		
		RC522_DELAY();
		RC522_SCK_1 ();
		
		RC522_DELAY();
	}
	return SPI_Data;
}
///////SPI END///////////////////////////////////////////////


/*******RC522寄存器操作函数**************************************************/

/****************************
 * 函数名：ReadRawRC
 * 描述  ：读RC522寄存器
 * 输入  ：ucAddress，寄存器地址
 * 返回  : 寄存器的当前值
 * 调用  ：内部调用
 ****************************/
uint8_t ReadRawRC ( uint8_t ucAddress )
{
	uint8_t ucAddr, ucReturn;
	
	ucAddr = ( ( ucAddress << 1 ) & 0x7E ) | 0x80;
	
	RC522_CS_Enable();
	
	SPI_RC522_SendByte ( ucAddr );
	ucReturn = SPI_RC522_ReadByte ();
	
	RC522_CS_Disable();
	
	return ucReturn;
}


/*
 * 函数名：WriteRawRC
 * 描述  ：写RC522寄存器
 * 输入  ：ucAddress，寄存器地址
 *         ucValue，写入寄存器的值
 * 返回  : 无
 * 调用  ：内部调用
 */
void WriteRawRC ( uint8_t ucAddress, uint8_t ucValue )
{  
	uint8_t ucAddr;

	ucAddr = ( ucAddress << 1 ) & 0x7E;
	
	RC522_CS_Enable();
	
	SPI_RC522_SendByte ( ucAddr );
	
	SPI_RC522_SendByte ( ucValue );
	
	RC522_CS_Disable();	
}


/*
 * 函数名：SetBitMask
 * 描述  ：对RC522寄存器置位
 * 输入  ：ucReg，寄存器地址
 *         ucMask，置位值
 * 返回  : 无
 * 调用  ：内部调用
 */
void SetBitMask ( uint8_t ucReg, uint8_t ucMask )  
{
    uint8_t ucTemp;

    ucTemp = ReadRawRC ( ucReg );
	
    WriteRawRC ( ucReg, ucTemp | ucMask );         // set bit mask
}


/*
 * 函数名：ClearBitMask
 * 描述  ：对RC522寄存器清位
 * 输入  ：ucReg，寄存器地址
 *         ucMask，清位值
 * 返回  : 无
 * 调用  ：内部调用
 */
void ClearBitMask ( uint8_t ucReg, uint8_t ucMask )  
{
    uint8_t ucTemp;

    ucTemp = ReadRawRC ( ucReg );
	
    WriteRawRC ( ucReg, ucTemp & ( ~ ucMask) );  // clear bit mask
}

/*******RC522寄存器操作函数 END**************************************************/


/*
 * 函数名：PcdAntennaOn
 * 描述  ：开启天线 
 * 输入  ：无
 * 返回  : 无
 * 调用  ：内部调用
 */
void PcdAntennaOn ( void )
{
    uint8_t uc;
    uc = ReadRawRC ( TxControlReg );
    if ( ! ( uc & 0x03 ) )
			SetBitMask(TxControlReg, 0x03);
}


/*
 * 函数名：PcdAntennaOff
 * 描述  ：关闭天线 
 * 输入  ：无
 * 返回  : 无
 * 调用  ：内部调用
 */
void PcdAntennaOff ( void )
{
    ClearBitMask ( TxControlReg, 0x03 );
}


/*
 * 函数名：PcdRese
 * 描述  ：复位RC522 
 * 输入  ：无
 * 返回  : 无
 * 调用  ：外部调用
 */
void PcdReset ( void )
{
    RC522_Reset_Disable();
    delay_us ( 1 );
    RC522_Reset_Enable();
    delay_us ( 1 );
	  RC522_Reset_Disable();
    delay_us ( 1 );
    WriteRawRC ( CommandReg, 0x0f );
    while ( ReadRawRC ( CommandReg ) & 0x10 );
    delay_us ( 1 );
    WriteRawRC ( ModeReg, 0x3D );            //定义发送和接收常用模式 和Mifare卡通讯，CRC初始值0x6363
    WriteRawRC ( TReloadRegL, 30 );          //16位定时器低位    
    WriteRawRC ( TReloadRegH, 0 );			     //16位定时器高位
    WriteRawRC ( TModeReg, 0x8D );				   //定义内部定时器的设置
    WriteRawRC ( TPrescalerReg, 0x3E );			 //设置定时器分频系数
    WriteRawRC ( TxAutoReg, 0x40 );				   //调制发送信号为100%ASK	
}


/*
 * 函数名：M500PcdConfigISOType
 * 描述  ：设置RC522的工作方式
 * 输入  ：ucType，工作方式
 * 返回  : 无
 * 调用  ：外部调用
 */
void M500PcdConfigISOType ( uint8_t ucType )
{
	if ( ucType == 'A')                     //ISO14443_A
	{
		ClearBitMask ( Status2Reg, 0x08 );
		WriteRawRC ( ModeReg, 0x3D );//3F		
		WriteRawRC ( RxSelReg, 0x86 );//84		
		WriteRawRC( RFCfgReg, 0x7F );   //4F		
		WriteRawRC( TReloadRegL, 30 );//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 		
		WriteRawRC ( TReloadRegH, 0 );		
		WriteRawRC ( TModeReg, 0x8D );		
		WriteRawRC ( TPrescalerReg, 0x3E );		
		delay_us ( 2 );		
		PcdAntennaOn ();//开天线
	}
}


/*
 * 函数名：PcdComMF522
 * 描述  ：通过RC522和ISO14443卡通讯
 * 输入  ：ucCommand，RC522命令字
 *         pInData，通过RC522发送到卡片的数据
 *         ucInLenByte，发送数据的字节长度
 *         pOutData，接收到的卡片返回数据
 *         pOutLenBit，返回数据的位长度
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：内部调用
 */
char PcdComMF522 ( uint8_t ucCommand, uint8_t * pInData, uint8_t ucInLenByte, uint8_t * pOutData, uint32_t * pOutLenBit )		
{
    char cStatus = MI_ERR;
    uint8_t ucIrqEn   = 0x00;
    uint8_t ucWaitFor = 0x00;
    uint8_t ucLastBits;
    uint8_t ucN;
    uint32_t ul;

    switch ( ucCommand )
    {
       case PCD_AUTHENT:		//Mifare认证
          ucIrqEn   = 0x12;		//允许错误中断请求ErrIEn  允许空闲中断IdleIEn
          ucWaitFor = 0x10;		//认证寻卡等待时候 查询空闲中断标志位
          break;
			 
       case PCD_TRANSCEIVE:		//接收发送 发送接收
          ucIrqEn   = 0x77;		//允许TxIEn RxIEn IdleIEn LoAlertIEn ErrIEn TimerIEn
          ucWaitFor = 0x30;		//寻卡等待时候 查询接收中断标志位与 空闲中断标志位
          break; 
       default:
         break; 
    }
   
    WriteRawRC ( ComIEnReg, ucIrqEn | 0x80 );		//IRqInv置位管脚IRQ与Status1Reg的IRq位的值相反 
    ClearBitMask ( ComIrqReg, 0x80 );			//Set1该位清零时，CommIRqReg的屏蔽位清零
    WriteRawRC ( CommandReg, PCD_IDLE );		//写空闲命令
    SetBitMask ( FIFOLevelReg, 0x80 );			//置位FlushBuffer清除内部FIFO的读和写指针以及ErrReg的BufferOvfl标志位被清除
    
    for ( ul = 0; ul < ucInLenByte; ul ++ )
		  WriteRawRC ( FIFODataReg, pInData [ ul ] );    		//写数据进FIFOdata
			
    WriteRawRC ( CommandReg, ucCommand );					//写命令
   
    
    if ( ucCommand == PCD_TRANSCEIVE )
			SetBitMask(BitFramingReg,0x80);  				//StartSend置位启动数据发送 该位与收发命令使用时才有效
    
    ul = 1000;//根据时钟频率调整，操作M1卡最大等待时间25ms
		
    do 														//认证 与寻卡等待时间	
    {
         ucN = ReadRawRC ( ComIrqReg );							//查询事件中断
         ul --;
    } while ( ( ul != 0 ) && ( ! ( ucN & 0x01 ) ) && ( ! ( ucN & ucWaitFor ) ) );		//退出条件i=0,定时器中断，与写空闲命令
		
    ClearBitMask ( BitFramingReg, 0x80 );					//清理允许StartSend位
		
    if ( ul != 0 )
    {
		if ( ! (( ReadRawRC ( ErrorReg ) & 0x1B )) )			//读错误标志寄存器BufferOfI CollErr ParityErr ProtocolErr
		{
			cStatus = MI_OK;
			
			if ( ucN & ucIrqEn & 0x01 )					//是否发生定时器中断
			  cStatus = MI_NOTAGERR;   
				
			if ( ucCommand == PCD_TRANSCEIVE )
			{
				ucN = ReadRawRC ( FIFOLevelReg );			//读FIFO中保存的字节数
				
				ucLastBits = ReadRawRC ( ControlReg ) & 0x07;	//最后接收到得字节的有效位数
				
				if ( ucLastBits )
					* pOutLenBit = ( ucN - 1 ) * 8 + ucLastBits;   	//N个字节数减去1（最后一个字节）+最后一位的位数 读取到的数据总位数
				else
					* pOutLenBit = ucN * 8;   					//最后接收到的字节整个字节有效
				
				if ( ucN == 0 )	
                    ucN = 1;    
				
				if ( ucN > MAXRLEN )
					ucN = MAXRLEN;   
				
				for ( ul = 0; ul < ucN; ul ++ )
				  pOutData [ ul ] = ReadRawRC ( FIFODataReg );   
			}		
        }
			else
				cStatus = MI_ERR;   
//			printf(ErrorReg);
    }
   
   SetBitMask ( ControlReg, 0x80 );           // stop timer now
   WriteRawRC ( CommandReg, PCD_IDLE ); 
	
   return cStatus;

}


/*
 * 函数名：PcdRequest
 * 描述  ：寻卡
 * 输入  ：ucReq_code，寻卡方式
 *                     = 0x52，寻感应区内所有符合14443A标准的卡
 *                     = 0x26，寻未进入休眠状态的卡
 *         pTagType，卡片类型代码
 *                   = 0x4400，Mifare_UltraLight
 *                   = 0x0400，Mifare_One(S50)
 *                   = 0x0200，Mifare_One(S70)
 *                   = 0x0800，Mifare_Pro(X))
 *                   = 0x4403，Mifare_DESFire
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：外部调用
 */
char PcdRequest ( uint8_t ucReq_code, uint8_t * pTagType )
{
    char cStatus;  
    uint8_t ucComMF522Buf [ MAXRLEN ]; 
    u32 ulLen;
    ClearBitMask ( Status2Reg, 0x08 );	//清理指示MIFARECyptol单元接通以及所有卡的数据通信被加密的情况
    WriteRawRC ( BitFramingReg, 0x07 );	//	发送的最后一个字节的 七位
    SetBitMask ( TxControlReg, 0x03 );	//TX1,TX2管脚的输出信号传递经发送调制的13.56的能量载波信号
    ucComMF522Buf [ 0 ] = ucReq_code;		//存入 卡片命令字
    cStatus = PcdComMF522 ( PCD_TRANSCEIVE,	ucComMF522Buf, 1, ucComMF522Buf, & ulLen );	//寻卡  
    if ( ( cStatus == MI_OK ) && ( ulLen == 0x10 ) )	//寻卡成功返回卡类型 
    {    
       * pTagType = ucComMF522Buf [ 0 ];
       * ( pTagType + 1 ) = ucComMF522Buf [ 1 ];
    }
    else
     cStatus = MI_ERR;
    return cStatus;
}


/*
 * 函数名：PcdAnticoll
 * 描述  ：防冲撞
 * 输入  ：pSnr，卡片序列号，4字节
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：外部调用
 */
char PcdAnticoll ( uint8_t * pSnr )
{
    char cStatus;
    uint8_t uc, ucSnr_check = 0;
    uint8_t ucComMF522Buf [ MAXRLEN ]; 
		uint32_t ulLen;

    ClearBitMask ( Status2Reg, 0x08 );		//清MFCryptol On位 只有成功执行MFAuthent命令后，该位才能置位
    WriteRawRC ( BitFramingReg, 0x00);		//清理寄存器 停止收发
    ClearBitMask ( CollReg, 0x80 );			//清ValuesAfterColl所有接收的位在冲突后被清除
   
    ucComMF522Buf [ 0 ] = 0x93;	//卡片防冲突命令
    ucComMF522Buf [ 1 ] = 0x20;
   
    cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, & ulLen);//与卡片通信
	
    if ( cStatus == MI_OK)		//通信成功
    {
		for ( uc = 0; uc < 4; uc ++ )
        {
            * ( pSnr + uc )  = ucComMF522Buf [ uc ];			//读出UID
            ucSnr_check ^= ucComMF522Buf [ uc ];
        }
			
        if ( ucSnr_check != ucComMF522Buf [ uc ] )
        		cStatus = MI_ERR;    
				 
    }
    
    SetBitMask ( CollReg, 0x80 );

    return cStatus;
	
}


/*
 * 函数名：CalulateCRC
 * 描述  ：用RC522计算CRC16
 * 输入  ：pIndata，计算CRC16的数组
 *         ucLen，计算CRC16的数组字节长度
 *         pOutData，存放计算结果存放的首地址
 * 返回  : 无
 * 调用  ：内部调用
 */
void CalulateCRC ( uint8_t * pIndata, uint8_t ucLen, uint8_t * pOutData )
{
    uint8_t uc, ucN;

    ClearBitMask(DivIrqReg,0x04);
	
    WriteRawRC(CommandReg,PCD_IDLE);
	
    SetBitMask(FIFOLevelReg,0x80);
	
    for ( uc = 0; uc < ucLen; uc ++)
	    WriteRawRC ( FIFODataReg, * ( pIndata + uc ) );   

    WriteRawRC ( CommandReg, PCD_CALCCRC );
	
    uc = 0xFF;
	
    do 
    {
        ucN = ReadRawRC ( DivIrqReg );
        uc --;
    } while ( ( uc != 0 ) && ! ( ucN & 0x04 ) );
		
    pOutData [ 0 ] = ReadRawRC ( CRCResultRegL );
    pOutData [ 1 ] = ReadRawRC ( CRCResultRegM );
	
}


/*
 * 函数名：PcdSelect
 * 描述  ：选定卡片
 * 输入  ：pSnr，卡片序列号，4字节
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：外部调用
 */
char PcdSelect ( uint8_t * pSnr )
{
	char ucN;
	uint8_t uc;
	uint8_t ucComMF522Buf [ MAXRLEN ]; 
	u32  ulLen;
	
	ucComMF522Buf [ 0 ] = PICC_ANTICOLL1;
	ucComMF522Buf [ 1 ] = 0x70;
	ucComMF522Buf [ 6 ] = 0;
	
	for ( uc = 0; uc < 4; uc ++ )
	{
		ucComMF522Buf [ uc + 2 ] = * ( pSnr + uc );
		ucComMF522Buf [ 6 ] ^= * ( pSnr + uc );
	}
	CalulateCRC ( ucComMF522Buf, 7, & ucComMF522Buf [ 7 ] );
	
	ClearBitMask ( Status2Reg, 0x08 );
	
	ucN = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, & ulLen );
	
	if ( ( ucN == MI_OK ) && ( ulLen == 0x18 ) )
		ucN = MI_OK;  
	else
		ucN = MI_ERR;    
	return ucN;
}


/*
 * 函数名：PcdAuthState
 * 描述  ：验证卡片密码
 * 输入  ：ucAuth_mode，密码验证模式
 *                     = 0x60，验证A密钥
 *                     = 0x61，验证B密钥
 *         uint8_t ucAddr，块地址
 *         pKey，密码
 *         pSnr，卡片序列号，4字节
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：外部调用
 */
char PcdAuthState ( uint8_t ucAuth_mode, uint8_t ucAddr, uint8_t * pKey, uint8_t * pSnr )
{
	char cStatus;
	uint8_t uc, ucComMF522Buf [ MAXRLEN ];
	u32 ulLen;
	
	ucComMF522Buf [ 0 ] = ucAuth_mode;
	ucComMF522Buf [ 1 ] = ucAddr;
	
	for ( uc = 0; uc < 6; uc ++ )
		ucComMF522Buf [ uc + 2 ] = * ( pKey + uc );   
	
	for ( uc = 0; uc < 6; uc ++ )
		ucComMF522Buf [ uc + 8 ] = * ( pSnr + uc );   
	
	cStatus = PcdComMF522 ( PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, & ulLen );
	
	if ( ( cStatus != MI_OK ) || ( ! ( ReadRawRC ( Status2Reg ) & 0x08 ) ) )
	{
	//			if(cStatus != MI_OK)
	//					printf("666")	;		
	//			else
	//				printf("888");
	cStatus = MI_ERR; 
	}
	return cStatus;
}


/*
 * 函数名：PcdWrite
 * 描述  ：写数据到M1卡一块
 * 输入  ：uint8_t ucAddr，块地址
 *         pData，写入的数据，16字节
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：外部调用
 */
char PcdWrite ( uint8_t ucAddr, uint8_t * pData )
{
	char cStatus;
	uint8_t uc, ucComMF522Buf [ MAXRLEN ];
	uint32_t ulLen;
	
	ucComMF522Buf [ 0 ] = PICC_WRITE;
	ucComMF522Buf [ 1 ] = ucAddr;
	
	CalulateCRC ( ucComMF522Buf, 2, &ucComMF522Buf [ 2 ] );
	
	cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &ulLen );
	
	if ( ( cStatus != MI_OK ) || ( ulLen != 4 ) || ( ( ucComMF522Buf [ 0 ] & 0x0F ) != 0x0A ) )
		cStatus = MI_ERR;   
	
	if ( cStatus == MI_OK )
	{
		//memcpy(ucComMF522Buf, &pData, 16);
		memcpy(ucComMF522Buf, pData, 16);
//		for ( uc = 0; uc < 16; uc ++ )
//			ucComMF522Buf [ uc ] = * ( pData + uc ); 
		for (uc = 0; uc < 16; uc++)
			ucComMF522Buf[uc] = pData[uc];
		
		CalulateCRC ( ucComMF522Buf, 16, & ucComMF522Buf [ 16 ] );
		
		cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, & ulLen );
		
		if (( cStatus != MI_OK ) || ( ulLen != 4 ) || (( ucComMF522Buf [0] & 0x0F ) != 0x0A ))
			cStatus = MI_ERR;   
	
	} 
	return cStatus;
}


/*
 * 函数名：PcdRead
 * 描述  ：读取M1卡一块数据
 * 输入  ：uint8_t ucAddr，块地址
 *         pData，读出的数据，16字节
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：外部调用
 */
char PcdRead ( uint8_t ucAddr, uint8_t * pData )
{
	char cStatus;
	uint8_t uc, ucComMF522Buf [ MAXRLEN ]; 
	uint32_t ulLen;
	
	ucComMF522Buf [ 0 ] = PICC_READ;
	ucComMF522Buf [ 1 ] = ucAddr;
	
	CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
	
	cStatus = PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );
	
	if ((cStatus == MI_OK) && (ulLen == 0x90))
	{
		for (uc = 0; uc < 16; uc ++)
			*(pData + uc) = ucComMF522Buf[uc];   
	}
	else
		cStatus = MI_ERR;   
	return cStatus;
}


/*
 * 函数名：PcdHalt
 * 描述  ：命令卡片进入休眠状态
 * 输入  ：无
 * 返回  : 状态值
 *         = MI_OK，成功
 * 调用  ：外部调用
 */
char PcdHalt( void )
{
    uint8_t ucComMF522Buf [ MAXRLEN ]; 
    u32  ulLen;

    ucComMF522Buf [ 0 ] = PICC_HALT;
    ucComMF522Buf [ 1 ] = 0;

    CalulateCRC ( ucComMF522Buf, 2, & ucComMF522Buf [ 2 ] );
    PcdComMF522 ( PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, & ulLen );

    return MI_OK;
	
}


void IC_CMT ( uint8_t * UID, uint8_t * KEY, uint8_t RW, uint8_t * Dat )
{
    uint8_t ucArray_ID [ 4 ] = { 0 };//先后存放IC卡的类型和UID(IC卡序列号)

    PcdRequest ( 0x52, ucArray_ID );//寻卡

    PcdAnticoll ( ucArray_ID );//防冲撞

    PcdSelect ( UID );//选定卡

    PcdAuthState ( 0x60, 0x10, KEY, UID );//校验

    if ( RW )//读写选择，1是读，0是写
        PcdRead ( 0x10, Dat );

    else 
        PcdWrite ( 0x10, Dat );
     
    PcdHalt ();	 
	 
}

void ShowID(uint16_t x,uint16_t y, uint8_t *p, uint16_t charColor, uint16_t bkColor)	 //显示卡的卡号，以十六进制显示
{
	uint8_t num[9];
	uint8_t i;

 	for(i=0;i<4;i++)
	{
		num[i*2]=p[i]/16;
		num[i*2]>9?(num[i*2]+='7'):(num[i*2]+='0');
		num[i*2+1]=p[i]%16;
		num[i*2+1]>9?(num[i*2+1]+='7'):(num[i*2+1]+='0');
	}
	num[8]=0;
    
 /*   LCD_ShowString(6,110,110,16,16,num); */
    printf("ID>>>%s\r\n", num);

}
void bytesToHexstring(unsigned char *bytes, int bytelength, char *hexstring, int hexstrlength)
{
	int i = 0,j = 0,b = 0;
	char s1,s2;
	char str2[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
  
  for (i = 0, j = 0; (i < bytelength) && (j < hexstrlength); i++, j++)
  {
    b = 0x0f & (bytes[i] >> 4);
    s1 = str2[b];
    hexstring[j] = s1;
    b = 0x0f & bytes[i];
    s2 = str2[b];
    j++;
    hexstring[j] = s2;
  }
}
